/**
 * Copyright (c) 2020 - present, Inspur Genersoft Co., Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
import { Ref, ref, watch } from 'vue';
import { DataGridColumn, DataGridProps } from '../data-grid.props';
import { VisualData, UseCellPosition, VisualDataCell } from './types';
import { ColumnRenderContext } from './use-column';

export function useCellPosition(props: DataGridProps, context: Ref<ColumnRenderContext>): UseCellPosition {
    const rowHeight = props.rowOption?.height || 28;
    const gridViewWidth = ref(context.value.primaryColumnsWidth);

    function calculateCellPositionInRow(columns: DataGridColumn[]) {
        const positionMap = {} as Record<string, { left: number; width: number }>;
        columns.reduce(
            (latestPosition: Record<string, { left: number; width: number }>, currentColumn: DataGridColumn, columnIndex: number) => {
                const nextColumn = columnIndex < columns.length - 1 ? columns[columnIndex + 1] : null;
                if (columnIndex === 0) {
                    latestPosition[currentColumn.field] = { left: 0, width: 0 };
                }
                latestPosition[currentColumn.field].width = currentColumn.actualWidth || 0;
                if (nextColumn) {
                    latestPosition[nextColumn.field] = {
                        left: latestPosition[currentColumn.field].left + (currentColumn.actualWidth || 0),
                        width: 0
                    };
                }
                return latestPosition;
            },
            positionMap
        );
        return positionMap;
    }

    function groupCellPosition(
        groupCell: VisualDataCell,
        cellPositionMap: Record<string, { left: number; width: number }>,
        layer: number
    ): Record<string, any> {
        const prefixOffset = rowHeight * (layer + 1);
        const widthBeforeGroup = cellPositionMap[groupCell.field].left - prefixOffset;
        const groupCellWidth = widthBeforeGroup + cellPositionMap[groupCell.field].width;
        const cellHeight = groupCell.parent.height ? `${groupCell.parent.height}px` : '';
        const styleObject = {
            left: `${prefixOffset}px`,
            width: `${groupCellWidth}px`,
            height: `${cellHeight}`
        } as Record<string, any>;
        return styleObject;
    }

    function summaryCellPosition(
        summaryCell: VisualDataCell,
        cellPositionMap: Record<string, { left: number; width: number }>,
        layer: number
    ): Record<string, any> {
        const cellHeight = summaryCell.parent.height ? `${summaryCell.parent.height}px` : '';
        const styleObject = {
            right: `0px`,
            height: `${cellHeight}`
        } as Record<string, any>;
        return styleObject;
    }

    function cellPosition(cell: VisualDataCell, cellPositionMap: Record<string, { left: number; width: number }>): Record<string, any> {
        const cellHeight = cell.parent.height ? `${cell.parent.height}px` : '';
        const styleObject = {
            left: `${cellPositionMap[cell.field].left}px`,
            width: `${cellPositionMap[cell.field].width}px`,
            height: `${cellHeight}`
        } as Record<string, any>;
        return styleObject;
    }

    function rowSpanCellPosition(
        visualDataItem: VisualData,
        cell: VisualDataCell,
        cellPositionMap: Record<string, { left: number; width: number }>
    ): Record<string, any> {
        const spannedCells = cell.spanned || [];
        const rowHeight =
            spannedCells.reduce((latestRowHeight: number, spannedCell: VisualDataCell) => {
                return latestRowHeight + (spannedCell.parent.height || 0);
            }, 0) + (visualDataItem.height || 0);
        const styleObject = {
            top: `${visualDataItem.top}px`,
            left: `${cellPositionMap[cell.field].left}px`,
            width: `${cellPositionMap[cell.field].width}px`,
            height: `${rowHeight}px`,
            padding: `calc(${rowHeight / 2}px - 1rem) 0`
            // height: `calc(${rowHeight}px * ${cell.rowSpan})`,
            // padding: `calc(${rowHeight * cell.rowSpan / 2}px - 1rem) 0`
        } as Record<string, any>;
        return styleObject;
    }

    function cellKey(dataItem: VisualData, columnIndex: number) {
        return `${dataItem.type}_r_${dataItem.index}_c_${columnIndex}_${dataItem.refreshKey || ''}`;
    }

    function rowKey(dataItem: VisualData) {
        return `${dataItem.type}_r_${dataItem.index}_${dataItem.refreshKey || ''}`;
    }

    function rowPosition(dataItem: VisualData): Record<string, any> {
        const rowHeight = dataItem.height ? `${dataItem.height}px` : '';
        const styleObject = {
            top: `${dataItem.top}px`,
            width: `${gridViewWidth.value}px`,
            height: `${rowHeight}`
        } as Record<string, any>;
        return styleObject;
    }

    watch(context, () => {
        gridViewWidth.value = context.value.primaryColumnsWidth;
    });

    return {
        calculateCellPositionInRow,
        cellKey,
        cellPosition,
        groupCellPosition,
        rowKey,
        rowPosition,
        rowSpanCellPosition,
        summaryCellPosition
    };
}
